home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Dev / SmallTalk / Behavior.st < prev    next >
Text File  |  1995-08-25  |  13KB  |  511 lines

  1. "======================================================================
  2. |
  3. |   Behavior Method Definitions
  4. |
  5.  ======================================================================"
  6.  
  7.  
  8. "======================================================================
  9. |
  10. | Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
  11. | Written by Steve Byrne.
  12. |
  13. | This file is part of GNU Smalltalk.
  14. |
  15. | GNU Smalltalk is free software; you can redistribute it and/or modify it
  16. | under the terms of the GNU General Public License as published by the Free
  17. | Software Foundation; either version 1, or (at your option) any later version.
  18. | GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
  19. | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  20. | FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  21. | details.
  22. | You should have received a copy of the GNU General Public License along with
  23. | GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
  24. | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  
  25. |
  26.  ======================================================================"
  27.  
  28.  
  29. "
  30. |     Change Log
  31. | ============================================================================
  32. | Author       Date       Change 
  33. | sbb         20 Apr 91      added methodsFor:ifFeatures:
  34. |
  35. | sbb         16 Mar 91      Class creation now separate statement.
  36. |
  37. | sbb         10 Nov 90      Implemented compile:notifying:
  38. |
  39. | sbb          1 Nov 90      Fixed isBytes to return true only if the object is
  40. |              not pointers and not words.
  41. |
  42. | sbb         21 Sep 90      Changed allSubclassesDo: to use ALL subclasses, both
  43. |              direct and indirect.
  44. |
  45. | sbb         16 Sep 90      Implemented whichSelectorsReferTo: and
  46. |              scopeHas:ifTrue:.
  47. |
  48. | sbyrne     25 Apr 89      created.
  49. |
  50. "
  51.  
  52. Object subclass: #Behavior
  53.        instanceVariableNames: 'superClass subClasses 
  54.                                methodDictionary instanceSpec'
  55.        classVariableNames: ''
  56.        poolDictionaries: ''
  57.        category: nil
  58. !
  59.  
  60. Behavior comment: 
  61. 'I am the parent class of all "class" type methods.  My instances know
  62. about the subclass/superclass relationships between classes, contain
  63. the description that instances are created from, and hold the method
  64. dictionary that''s associated with each class.  I provide methods for
  65. compiling methods, modifying the class inheritance hierarchy, examining the
  66. method dictionary, and iterating over the class hierarchy.' !
  67.  
  68. CFunctionDescs at: #CFunctionGensym put: 1!
  69.  
  70. !Behavior class methodsFor: 'C interface'!
  71.  
  72. defineCFunc: cFuncNameString
  73.   withSelectorArgs: selectorAndArgs
  74.   forClass: aClass 
  75.   returning: returnTypeSymbol 
  76.   args: argsArray
  77.     | stream gensym descriptor |
  78.     "This is pretty complex.  What I want to provide is a very efficient way
  79.      of calling a C function.  I create a descriptor object that holds the
  80.      relevant information regarding the C function.  I then compile the
  81.      method that's to be invoked to call the C function.  This method uses the
  82.      primitive #255 to perform the actual call-out.  To let the primitive
  83.      know which descriptor to use, I arrange for the first and only method
  84.      literal of the compiled method to be an association that contains as
  85.      its value the C function descriptor object.  I add new associations to
  86.      the global shared pool 'CFunctionDescs', and reference the newly
  87.      generated key in the text of the compiled method."
  88.     gensym _ Symbol intern: ('CFunction' , CFunctionGensym printString).
  89.     CFunctionGensym _ CFunctionGensym + 1.
  90.     descriptor _ self makeDescriptorFor: cFuncNameString
  91.                       returning: returnTypeSymbol
  92.                   withArgs: argsArray.
  93.     CFunctionDescs at: gensym put: descriptor.
  94.     stream _ WriteStream on: (String new: 20).
  95.     stream nextPutAll: selectorAndArgs;
  96.     nextPutAll:
  97. '
  98.     <primitive: 255>
  99.     ^';
  100.     print: gensym.
  101.     aClass compile: stream contents
  102. !!
  103.  
  104.  
  105.  
  106. !Behavior methodsFor: 'creating method dictionary'!
  107.  
  108. methodDictionary: aDictionary
  109.     methodDictionary _ aDictionary
  110. !
  111.  
  112. addSelector: selector withMethod: compiledMethod
  113.     methodDictionary at: selector put: compiledMethod
  114. !
  115.  
  116. removeSelector: selector
  117.     methodDictionary removeKey: selector
  118. !
  119.  
  120. compile: code
  121.     (code isKindOf: PositionableStream)
  122.         ifTrue: [ code _ code contents ].
  123.     (code isMemberOf: String)
  124.         ifFalse: [ code _ code asString ].
  125.     ^self compileString: code
  126. !
  127.  
  128. compile: code notifying: requestor
  129.     | method |
  130.     method _ self compile: code.
  131.     method isNil ifTrue:
  132.     [ ^requestor error: 'Compilation failed' ].
  133.     ^method
  134. !
  135.  
  136. recompile: selector
  137.     self compile: (self sourceCodeAt: selector)
  138. !
  139.  
  140. decompile: selector
  141.     | method source |
  142.     method _ self compiledMethodAt: selector.
  143.     source _ method methodSourceString.
  144.     source isNil
  145.         ifTrue: [ ^self error: 'decompiler can''t decompile methods without source (yet)' ]
  146.     ifFalse: [ ^source ]
  147. !
  148.  
  149. edit: selector
  150.     | method sourceFile sourcePos |
  151.     method _ self compiledMethodAt: selector.
  152.     sourceFile _ method methodSourceFile.
  153.     sourceFile isNil
  154.         ifTrue: [ ^self error: 'decompiler can''t decompile methods without source (yet)' ].
  155.     sourcePos _ method methodSourcePos.
  156.     Smalltalk system: 'emacs -l st -smalltalk ', sourceFile, ' ', sourcePos printString
  157. !
  158.  
  159. compileAll
  160.     methodDictionary notNil
  161.     ifTrue: [ methodDictionary keysDo: 
  162.               [ :selector | self recompile: selector ] ]
  163. !
  164.  
  165. compileAllSubclasses
  166.     self allSubclassesDo: [ :subclass | subclass compileAll ]
  167. !!
  168.  
  169.  
  170.  
  171. !Behavior methodsFor: 'creating a class hierarchy'!
  172.  
  173. superclass: aClass
  174.     superClass _ aClass
  175. !
  176.  
  177. addSubclass: aClass
  178.     subClasses isNil 
  179.     ifTrue: [ subClasses _ Array new: 0 ]
  180.     ifFalse: [ "remove old class if any"
  181.           subClasses _ subClasses copyWithout: aClass ].
  182.     subClasses _ subClasses copyWith: aClass
  183. !
  184.  
  185. removeSubclass: aClass
  186.     subClasses _ subClasses copyWithout: aClass
  187. !!
  188.  
  189.  
  190.  
  191. !Behavior methodsFor: 'accessing the methodDictionary'!
  192.  
  193. selectors
  194.     methodDictionary isNil
  195.         ifTrue: [ ^Set new ]
  196.     ifFalse: [ ^methodDictionary keys ]
  197. !
  198.  
  199. allSelectors
  200.     | aSet |
  201.     aSet _ self selectors.
  202.     self allSuperclassesDo:
  203.         [ :superclass | aSet addAll: superclass selectors ].
  204.     ^aSet
  205. !
  206.  
  207. compiledMethodAt: selector
  208.     "Return the compiled method associated with selector, from the local
  209.     method dictionary.  Error if not found."
  210.     ^methodDictionary at: selector
  211. !
  212.  
  213. sourceCodeAt: selector
  214.     | method |
  215.     method _ self compiledMethodAt: selector.
  216.     ^method methodSourceString
  217. !
  218.  
  219. sourceMethodAt: selector
  220.     "This is too dependent on the original implementation"
  221.     self shouldNotImplement
  222. !!
  223.  
  224.  
  225.  
  226. !Behavior methodsFor: 'accessing instances and variables'!
  227.  
  228. allInstances
  229.     "Returns a set of all instances of the receiver"
  230.     | aSet |
  231.     aSet _ Set new.
  232.     self allInstancesDo: [ :anInstance | aSet add: anInstance ].
  233.     ^aSet
  234. !
  235.  
  236. instanceCount
  237.     | count anInstance |
  238.     count _ 0.
  239.     anInstance _ self someInstance.
  240.     [ anInstance notNil ]
  241.         whileTrue: [ count _ count + 1.
  242.                  anInstance _ anInstance nextInstance ].    
  243.     ^count
  244. !
  245.     
  246. instVarNames
  247.     self subclassResponsibility "### is this right?  Why is it here instead of
  248.                                  in ClassDescription?"
  249. !
  250.  
  251. subclassInstVarNames
  252.     self subclassResponsibility
  253. !
  254.  
  255. allInstVarNames
  256.     self subclassResponsibility
  257. !
  258.  
  259. classVarNames
  260.     self subclassResponsibility 
  261. !
  262.  
  263. allClassVarNames
  264.     self subclassResponsibility
  265. !
  266.  
  267. sharedPools
  268.     self subclassResponsibility
  269. !
  270.  
  271. allSharedPools
  272.     self subclassResponsibility
  273. !!
  274.  
  275.  
  276.  
  277. !Behavior methodsFor: 'accessing class hierarchy'!
  278.  
  279. subclasses
  280.     subClasses isNil
  281.     ifTrue: [ ^Set new ]
  282.     ifFalse: [ ^subClasses asSet ]
  283. !
  284.  
  285. allSubclasses
  286.     | aSet |
  287.     aSet _ Set new.
  288.     self allSubclassesDo: [ :subclass | aSet add: subclass ].
  289.     ^aSet
  290. !
  291.  
  292. withAllSubclasses
  293.     | aSet |
  294.     aSet _ Set with: self.
  295.     aSet addAll: (self allSubclasses).
  296.     ^aSet
  297. !
  298.  
  299. superclass
  300.     ^superClass
  301. !
  302.  
  303. allSuperclasses
  304.     | supers |
  305.     supers _ OrderedCollection new.
  306.     self allSuperclassesDo:
  307.         [ :superclass | supers addLast: superclass ].
  308.     ^supers
  309. !!
  310.  
  311.  
  312.  
  313. !Behavior methodsFor: 'testing the method dictionary'!
  314.  
  315. hasMethods
  316.     ^methodDictionary notNil and: [ methodDictionary size ~= 0 ]
  317. !
  318.  
  319. includesSelector: selector
  320.     "Returns true if the local method dictionary"
  321.     ^methodDictionary notNil and: [ methodDictionary includesKey: selector ]
  322. !
  323.  
  324. canUnderstand: selector
  325.     (self includesSelector: selector)
  326.         ifTrue: [ ^true ].
  327.     self allSuperclassesDo:
  328.         [ :superclass | (superclass includesSelector: selector)
  329.                         ifTrue: [ ^true ] ].
  330.     ^false
  331. !
  332.  
  333. whichClassIncludesSelector: selector
  334.     self allSuperclassesDo:
  335.         [ :superclass | (superclass includesSelector: selector)
  336.                         ifTrue: [ ^superclass ] ].
  337.     ^nil
  338. !
  339.  
  340. whichSelectorsAccess: instVarName
  341.     self notYetImplemented
  342. !
  343.  
  344. whichSelectorsReferTo: anObject
  345.     "Returns a Set of selectors that refer to anObject"
  346.     | s method |
  347.     s _ Set new.
  348.     methodDictionary isNil
  349.     ifTrue: [ ^s ].
  350.     methodDictionary associationsDo:
  351.     [ :assoc |  method _ assoc value.
  352.             1 to: method numLiterals do:
  353.             [ :i | (method literalAt: i) == anObject
  354.                    ifTrue: [ s add: assoc key ]
  355.                    ]
  356.             ].
  357.     ^s
  358. !
  359.  
  360. scopeHas: name ifTrue: aBlock
  361.     | nameSym |
  362.     nameSym _ name asSymbol.
  363.     ((self allInstVarNames) includes: nameSym) ifTrue: [ ^aBlock value ].
  364.     ((self allClassVarNames) includes: nameSym) ifTrue: [ ^aBlock value ].
  365.     (self allSharedPools) do:
  366.     [ :dictName | ((Smalltalk at: dictName asSymbol) includesKey: nameSym)
  367.               ifTrue: [ ^aBlock value ] ]
  368. !!
  369.  
  370.  
  371.  
  372. !Behavior methodsFor: 'testing the form of the instances'!
  373.  
  374. isPointers
  375.     "Due to our representation bit 30 is inverted, so we invert the sense
  376.     of this test, and things work out fine."
  377.     ^(self instanceSpec bitAt: 30) = 0
  378. !
  379.  
  380. isBits
  381.     ^self isPointers not
  382. !
  383.  
  384. isBytes
  385.     ^self isPointers not & self isWords not
  386. !
  387.  
  388. isWords
  389.     ^(self instanceSpec bitAt: 29) ~= 0
  390. !
  391.  
  392. isFixed
  393.     ^self isVariable not
  394. !
  395.  
  396. isVariable
  397.     ^(self instanceSpec bitAt: 28) ~= 0
  398. !
  399.  
  400. instSize
  401.     ^self instanceSpec bitAnd: 16r0FFFFFFF
  402. !!
  403.  
  404.  
  405.  
  406. !Behavior methodsFor: 'testing the class hierarchy'!
  407.  
  408. inheritsFrom: aClass
  409.     "Returns true if aClass is a superclass of the receiver"
  410.     | sc |
  411.     sc _ self.
  412.     [ sc _ sc superclass.
  413.       sc isNil ]
  414.         whileFalse:
  415.         [ sc == aClass ifTrue: [ ^true ] ].
  416.     ^false
  417. !
  418.  
  419. kindOfSubclass
  420.     self isVariable
  421.         ifTrue: [ self isBytes ifTrue: [ ^'variableByteSubclass: ' ].
  422.               self isPointers
  423.             ifTrue: [ ^'variableSubclass: ' ]
  424.             ifFalse: [ ^'variableWordSubclass: ' ] ]
  425.     ifFalse: [ ^'subclass: ' ]
  426. !!
  427.  
  428.  
  429.  
  430. !Behavior methodsFor: 'enumerating'!
  431.  
  432. allSubclassesDo: aBlock
  433.     "Invokes aBlock for all subclasses, both direct and indirect."
  434.     subClasses notNil
  435.     ifTrue: [ subClasses do: [ :class | aBlock value: class.
  436.                         class allSubclassesDo: aBlock ]
  437.               ]
  438. !
  439.  
  440. allSuperclassesDo: aBlock
  441.     | class superclass |
  442.     class _ self.
  443.     [ superclass _ class superclass.
  444.       class _ superclass.
  445.       superclass notNil ] whileTrue:
  446.           [ aBlock value: superclass ]
  447. !
  448.  
  449. allInstancesDo: aBlock
  450.     | anInstance |
  451.     anInstance _ self someInstance.
  452.     [ anInstance notNil ]
  453.         whileTrue: [ aBlock value: anInstance.
  454.                  anInstance _ anInstance nextInstance ]
  455. !
  456.  
  457. allSubinstancesDo: aBlock
  458.     self allSubclassesDo:
  459.         [ :subclass | subclass allInstancesDo: aBlock ]
  460. !
  461.  
  462. selectSubclasses: aBlock
  463.     | aSet |
  464.     aSet _ Set new.
  465.     self allSubclassesDo: [ :subclass | (aBlock value: subclass)
  466.                                             ifTrue: [ aSet add: subclass ] ].
  467.     ^aSet
  468. !
  469.  
  470. selectSuperclasses: aBlock
  471.     | aSet |
  472.     aSet _ Set new.
  473.     self allSuperclassesDo: [ :superclass | (aBlock value: superclass)
  474.                                             ifTrue: [ aSet add: superclass ] ].
  475.     ^aSet
  476. !!
  477.  
  478.  
  479.  
  480. !Behavior methodsFor: 'conditional compilation'!
  481.  
  482. methodsFor: category ifFeatures: features
  483.     ^self methodsFor: category ifTrue: (Smalltalk hasFeatures: features)
  484. !!
  485.  
  486.  
  487.  
  488. !Behavior methodsFor: 'private'!
  489.  
  490. instanceSpec
  491.     ^instanceSpec
  492. !
  493.  
  494. setInstanceSpec: variableBoolean
  495.   words: wordsBoolean
  496.   pointers: pointersBoolean
  497.   instVars: anIntegerSize
  498.     instanceSpec _ 0.
  499.     "Due to our representation bit 30 is inverted, so we invert the sense
  500.     of this test, and things work out fine."
  501.     pointersBoolean
  502.         ifFalse: [ instanceSpec _ instanceSpec bitOr: ( 1 bitShift: 30 ) ].
  503.     wordsBoolean
  504.         ifTrue: [ instanceSpec _ instanceSpec bitOr: ( 1 bitShift: 29 ) ].
  505.     variableBoolean
  506.         ifTrue: [ instanceSpec _ instanceSpec bitOr: ( 1 bitShift: 28 ) ].
  507.     instanceSpec _ instanceSpec bitOr: (anIntegerSize bitAnd: 16r0FFFFFFF).
  508. !!
  509.